package framework.utils;

import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author	Orlin Tomov
 * @version	0.2 
 */
public class ArrayMap<K,V> extends AbstractMap<K,V> implements Cloneable, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	static class ArrayEntry<K, V> implements Entry<K, V> {
		protected K key;
		protected V value;

		public ArrayEntry(K key, V value) {
			this.key = key;
			this.value = value;
		}

		@Override
		public K getKey() {
			return key;
		}

		@Override
		public V getValue() {
			return value;
		}

		@Override
		public V setValue(V newValue) {
			V oldValue = value;
			value = newValue;
			return oldValue;
		}

		@Override
		public boolean equals(Object o) {
			if (o instanceof Entry) {
				return equals((Entry<?,?>)o);
			}
			return false;
		}

		public boolean equals(Entry<K,V> entry) {
			return (key==null ? entry.getKey()==null : key.equals(entry.getKey())) &&
			(value==null ? entry.getValue()==null : value.equals(entry.getValue()));
		}

		@Override
		public int hashCode() {
			int keyHash = (key==null ? 0 : key.hashCode());
			int valueHash = (value==null ? 0 : value.hashCode());
			return keyHash ^ valueHash;
		}

		@Override
		public String toString() {
			return key + "=" + value;
		}
	}

	private Set<Entry<K,V>> entries = null;
	private List<Entry<K,V>> list;

	public ArrayMap() {
		list = new ArrayList<Entry<K,V>>();
	}

	public ArrayMap(Map<K,V> map) {
		list = new ArrayList<Entry<K,V>>();
		putAll(map);
	}

	public ArrayMap(int initialCapacity) {
		list = new ArrayList<Entry<K,V>>(initialCapacity);
	}

	@Override
	public Set<Entry<K, V>> entrySet() {
		if (entries == null) {
			entries = new AbstractSet<Entry<K, V>>() {
				@Override
				public void clear() {
					list.clear();
				}

				@Override
				public Iterator<Entry<K, V>> iterator() {
					return list.iterator();
				}

				@Override
				public int size() {
					return list.size();
				}
			};
		}
		return entries;
	}

	@Override
	public V put(K key, V value) {
		int size = list.size();
		// System.out.println("size: " + size);
		Entry<K, V> entry = null;
		int i;
		if (key == null) {
			for (i = 0; i < size; i++) {
				entry = list.get(i);
				if (entry.getKey() == null) {
					break;
				}
			}
		} else {
			for (i = 0; i < size; i++) {
				entry = list.get(i);
				if (key.equals(entry.getKey())) {
					break;
				}
			}
		}
		V oldValue = null;
		if (i < size) {
			oldValue = entry.getValue();
			// entry.setValue(value);
		} // else {
		list.add(new ArrayEntry<K, V>(key, value));
		// }
		return oldValue;
	}

	@Override
	public V remove(Object key) {
		Iterator<Entry<K, V>> i = entrySet().iterator();
		Entry<K, V> correctEntry = null;
		if (key == null) {
			while (correctEntry == null && i.hasNext()) {
				Entry<K, V> e = i.next();
				if (e.getKey() == null) {
					correctEntry = e;
				}
			}
		} else {
			Entry<K, V> exactEntry = null;
			while (exactEntry == null && i.hasNext()) {
				Entry<K, V> e = i.next();
				if (key == e.getKey()) {
					exactEntry = e;
				} else if ((correctEntry == null) && (key.equals(e.getKey()))) {
					correctEntry = e;
				}
			}
			if (exactEntry != null) {
				correctEntry = exactEntry;
			} else if (correctEntry != null) {
				i = entrySet().iterator();
				while (i.hasNext()) {
					if (correctEntry == i.next()) {
						break;
					}
				}
			}
		}

		V oldValue = null;
		if (correctEntry != null) {
			oldValue = correctEntry.getValue();
			i.remove();
		}
		return oldValue;
	}

	@Override
	public Object clone() {
		return new ArrayMap<K, V>(this);
	}
}

